<?php

namespace ORM;

use Database\Connection;
use Database\QueryBuilder as DatabaseQueryBuilder;

class QueryBuilder {
    protected $connection;
    protected $model;
    protected $query;
    
    /**
     * 构造函数
     */
    public function __construct(Connection $connection, Model $model) {
        $this->connection = $connection;
        $this->model = $model;
        $this->query = new DatabaseQueryBuilder($connection);
        $this->query->table($model->getTable());
    }
    
    /**
     * 设置查询的列
     */
    public function select($columns = ['*']) {
        $this->query->select($columns);
        return $this;
    }
    
    /**
     * 添加where条件
     */
    public function where($column, $operator = null, $value = null, $boolean = 'AND') {
        $this->query->where($column, $operator, $value, $boolean);
        return $this;
    }
    
    /**
     * 添加OR WHERE条件
     */
    public function orWhere($column, $operator = null, $value = null) {
        $this->query->orWhere($column, $operator, $value);
        return $this;
    }
    
    /**
     * 添加WHERE IN条件
     */
    public function whereIn($column, array $values, $boolean = 'AND') {
        $this->query->whereIn($column, $values, $boolean);
        return $this;
    }
    
    /**
     * 添加ORDER BY子句
     */
    public function orderBy($column, $direction = 'ASC') {
        $this->query->orderBy($column, $direction);
        return $this;
    }
    
    /**
     * 设置LIMIT子句
     */
    public function limit($limit) {
        $this->query->limit($limit);
        return $this;
    }
    
    /**
     * 设置OFFSET子句
     */
    public function offset($offset) {
        $this->query->offset($offset);
        return $this;
    }
    
    /**
     * 添加JOIN子句
     */
    public function join($table, $first, $operator = null, $second = null, $type = 'INNER') {
        $this->query->join($table, $first, $operator, $second, $type);
        return $this;
    }
    
    /**
     * 添加LEFT JOIN子句
     */
    public function leftJoin($table, $first, $operator = null, $second = null) {
        $this->query->leftJoin($table, $first, $operator, $second);
        return $this;
    }
    
    /**
     * 添加GROUP BY子句
     */
    public function groupBy(...$groups) {
        $this->query->groupBy(...$groups);
        return $this;
    }
    
    /**
     * 添加HAVING子句
     */
    public function having($column, $operator = null, $value = null, $boolean = 'AND') {
        $this->query->having($column, $operator, $value, $boolean);
        return $this;
    }
    
    /**
     * 获取单条记录并转换为模型实例
     */
    public function first() {
        $result = $this->query->first();
        
        if (!$result) {
            return null;
        }
        
        return $this->model->newInstance($result);
    }
    
    /**
     * 获取所有记录并转换为模型实例集合
     */
    public function get() {
        $results = $this->query->get();
        $models = [];
        
        foreach ($results as $result) {
            $models[] = $this->model->newInstance($result);
        }
        
        return $models;
    }
    
    /**
     * 根据主键查找记录
     */
    public function find($id) {
        $primaryKey = $this->model->getPrimaryKey();
        return $this->where($primaryKey, $id)->first();
    }
    
    /**
     * 插入记录
     */
    public function insert(array $values) {
        return $this->query->insert($values);
    }
    
    /**
     * 更新记录
     */
    public function update(array $values) {
        return $this->query->update($values);
    }
    
    /**
     * 删除记录
     */
    public function delete() {
        return $this->query->delete();
    }
    
    /**
     * 生成完整的SQL语句
     */
    public function toSql() {
        return $this->query->toSql();
    }
    
    /**
     * 分页查询
     */
    public function paginate($perPage = 15, $page = null) {
        // 获取当前页码
        $page = $page ?: (isset($_GET['page']) ? (int) $_GET['page'] : 1);
        $page = $page < 1 ? 1 : $page;
        
        // 计算偏移量
        $offset = ($page - 1) * $perPage;
        
        // 获取总记录数
        $countQuery = clone $this->query;
        $total = count($countQuery->get());
        
        // 获取当前页的数据
        $this->query->limit($perPage)->offset($offset);
        $data = $this->get();
        
        // 计算总页数
        $lastPage = ceil($total / $perPage);
        
        return [
            'total' => $total,
            'per_page' => $perPage,
            'current_page' => $page,
            'last_page' => $lastPage,
            'data' => $data
        ];
    }
    
    /**
     * 聚合函数：计数
     */
    public function count($column = '*') {
        $result = $this->aggregate('COUNT', $column);
        return $result ? (int) $result : 0;
    }
    
    /**
     * 聚合函数：最大值
     */
    public function max($column) {
        return $this->aggregate('MAX', $column);
    }
    
    /**
     * 聚合函数：最小值
     */
    public function min($column) {
        return $this->aggregate('MIN', $column);
    }
    
    /**
     * 聚合函数：求和
     */
    public function sum($column) {
        $result = $this->aggregate('SUM', $column);
        return $result ? (float) $result : 0;
    }
    
    /**
     * 聚合函数：平均值
     */
    public function avg($column) {
        $result = $this->aggregate('AVG', $column);
        return $result ? (float) $result : 0;
    }
    
    /**
     * 执行聚合查询
     */
    protected function aggregate($function, $column) {
        $this->query->select(["$function($column) as aggregate"]);
        $result = $this->query->first();
        return $result ? $result['aggregate'] : null;
    }
    
    /**
     * 动态调用底层查询构建器的方法
     */
    public function __call($method, $parameters) {
        if (method_exists($this->query, $method)) {
            $result = $this->query->$method(...$parameters);
            
            if ($result instanceof DatabaseQueryBuilder) {
                return $this;
            }
            
            return $result;
        }
        
        throw new \BadMethodCallException("方法 [$method] 不存在");
    }
}